﻿using CL_VisionCommu_Test.Helper;
using ModbusMaster;
using System;
using System.Collections.Generic;
using System.Linq;

namespace CL_VisionCommu_Test.Device
{
    public enum DataType
    {
        USHORT,
        INT,
        FLOAT,
        DOUBLE,
        STRING,
        BOOL
    }

    public class CommuMasterCaller
    {
        List<CommuMaster> masters = new List<CommuMaster>();

        List<CommunicationParameters> parameters = new List<CommunicationParameters>();

        public string Init()
        {
            string ConnectedString = "";
            parameters = CommuConfiguration.GetParameters();
            for (int i = 0; i < parameters.Count; i++)
            {
                CommuMaster _master = new CommuMaster(parameters[i].Ip, parameters[i].Port);
                ConnectedString += parameters[i].Ip + "_" + parameters[i].Port.ToString() + ":" + _master.Connected.ToString() + "\r\n";
                masters.Add(_master);
            }
            return ConnectedString;
        }

        public int ReadConstantValue(int Index, string ConstantName)
        {
            int value = 0;
            if (masters.Count != 0 && masters.Count >= Index)
            {
                switch (ConstantName)
                {
                    case "RunStates":
                        value = masters[Index].ReadHoldingRegistersToUshort(1, 29);
                        break;
                    case "TestplanStates":
                        value = masters[Index].ReadHoldingRegistersToUshort(1, 30);
                        break;
                    case "ResultStates":
                        value = masters[Index].ReadHoldingRegistersToUshort(1, 31);
                        break;
                    case "Mode":
                        value = masters[Index].ReadHoldingRegistersToUshort(1, 32);
                        break;
                    case "HandShake00":
                        value = masters[Index].ReadHoldingRegistersToBool(1, 16) ;
                        break;
                    case "HandShake01":
                        value = masters[Index].ReadHoldingRegistersToBool(1, 17);
                        break;
                    case "HandShake02":
                        value = masters[Index].ReadHoldingRegistersToBool(1, 18) ;
                        break;
                    case "HandShake03":
                        value = masters[Index].ReadHoldingRegistersToBool(1, 19) ;
                        break;
                    case "HandShake04":
                        value = masters[Index].ReadHoldingRegistersToBool(1, 20);
                        break;
                    case "HandShake05":
                        value = masters[Index].ReadHoldingRegistersToBool(1, 21) ;
                        break;
                    case "HandShake06":
                        value = masters[Index].ReadHoldingRegistersToBool(1, 22);
                        break;
                    case "HandShake07":
                        value = masters[Index].ReadHoldingRegistersToBool(1, 23);
                        break;
                    default:
                        break;
                }
            }
            return value;
        }

        public bool WriteNCConstantValue(int Index, string ConstantName, double Value)
        {
            bool ret = false;
            try
            {
                if (masters.Count != 0 && masters.Count >= Index)
                {
                    switch (ConstantName)
                    {
                        case "Start check":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 0, (ushort)Value);
                            break;
                        case "Execute command":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 1, (ushort)Value);
                            break;
                        case "IHandshake0":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 2, (ushort)Value);
                            break;
                        case "IHandshake1":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 3, (ushort)Value);
                            break;
                        case "IHandshake2":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 4, (ushort)Value);
                            break;
                        case "IHandshake3":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 5, (ushort)Value);
                            break;
                        case "IHandshake4":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 6, (ushort)Value);
                            break;
                        case "IHandshake5":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 7, (ushort)Value);
                            break;
                        case "IHandshake6":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 8, (ushort)Value);
                            break;
                        case "IHandshake7":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 9, (ushort)Value);
                            break;
                        case "Command code":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 10, (ushort)Value);
                            break;
                        case "Command parameter":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 11, (ushort)Value);
                            break;
                        default:
                            break;
                    }
                }
                ret = true;
                return ret;
            }
            catch (Exception)
            {
                ret = false;
                return ret;
            }
        }

        public int ReadNCConstantValue(int Index, string ConstantName)
        {
            int value = 0;
            if (masters.Count != 0 && masters.Count >= Index)
            {
                switch (ConstantName)
                {
                    case "System alive":
                        value = masters[Index].ReadInputRegistersToBool(1, 0) == true ? 1 : 0;
                        break;
                    case "Automatic mode ready":
                        value = masters[Index].ReadInputRegistersToBool(1, 1) == true ? 1 : 0;
                        break;
                    case "System ready":
                        value = masters[Index].ReadInputRegistersToBool(1, 2) == true ? 1 : 0;
                        break;
                    case "Data valid":
                        value = masters[Index].ReadInputRegistersToBool(1, 3) == true ? 1 : 0;
                        break;
                    case "Check routine result O.K":
                        value = masters[Index].ReadInputRegistersToBool(1, 4) == true ? 1 : 0;
                        break;
                    case "Check routine result n.O.K":
                        value = masters[Index].ReadInputRegistersToBool(1, 5) == true ? 1 : 0;
                        break;
                    case "Self test failed":
                        value = masters[Index].ReadInputRegistersToBool(1, 6) == true ? 1 : 0;
                        break;
                    case "Event log full":
                        value = masters[Index].ReadInputRegistersToBool(1, 7) == true ? 1 : 0;
                        break;
                    case "OHandshake00":
                        value = masters[Index].ReadInputRegistersToBool(1, 8) == true ? 1 : 0;
                        break;
                    case "OHandshake01":
                        value = masters[Index].ReadInputRegistersToBool(1, 9) == true ? 1 : 0;
                        break;
                    case "OHandshake02":
                        value = masters[Index].ReadInputRegistersToBool(1, 10) == true ? 1 : 0;
                        break;
                    case "OHandshake03":
                        value = masters[Index].ReadInputRegistersToBool(1, 11) == true ? 1 : 0;
                        break;
                    case "OHandshake04":
                        value = masters[Index].ReadInputRegistersToBool(1, 12) == true ? 1 : 0;
                        break;
                    case "OHandshake05":
                        value = masters[Index].ReadInputRegistersToBool(1, 13) == true ? 1 : 0;
                        break;
                    case "OHandshake06":
                        value = masters[Index].ReadInputRegistersToBool(1, 14) == true ? 1 : 0;
                        break;
                    case "OHandshake07":
                        value = masters[Index].ReadInputRegistersToBool(1, 15) == true ? 1 : 0;
                        break;
                    case "Current check routine ID":
                        value = masters[Index].ReadInputRegistersToUshort(1, 16);
                        break;
                    case "Current security profile ID":
                        value = masters[Index].ReadInputRegistersToUshort(1, 17);
                        break;
                    case "Last command code":
                        value = masters[Index].ReadInputRegistersToUshort(1, 18);
                        break;
                    default:
                        break;
                }
            }
            return value;
        }

        public bool WriteConstantValue(int Index, string ConstantName, double Value)
        {
            bool ret = false;
            try
            {
                if (masters.Count != 0 && masters.Count >= Index)
                {
                    switch (ConstantName)
                    {
                        case "Command":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 0, (ushort)Value);
                            break;
                        case "ManFctNo":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 1, (ushort)Value);
                            break;
                        case "ParaDinit1":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 2, (ushort)Value);
                            break;
                        case "ParaDinit2":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 3, (ushort)Value);
                            break;
                        case "ParaDinit3":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 4, (ushort)Value);
                            break;
                        case "ParaDinit4":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 5, (ushort)Value);
                            break;
                        case "ParaReal1":
                            masters[Index].WriteHoldingRegisterFromFloat(0, 6, (float)Value);
                            break;
                        case "ParaReal2":
                            masters[Index].WriteHoldingRegisterFromFloat(0, 8, (float)Value);
                            break;
                        case "ParaReal3":
                            masters[Index].WriteHoldingRegisterFromFloat(0, 10, (float)Value);
                            break;
                        case "ParaReal4":
                            masters[Index].WriteHoldingRegisterFromFloat(0, 12, (float)Value);
                            break;
                        case "Para1":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 14, (ushort)Value);
                            break;
                        case "Para2":
                            masters[Index].WriteHoldingRegisterFromUshort(0, 15, (ushort)Value);
                            break;
                        case "HandShake00":
                            masters[Index].WriteSingleRegister(0, 16, (ushort)Value);
                            break;
                        case "HandShake01":
                            masters[Index].WriteSingleRegister(0, 17, (ushort)Value);
                            break;
                        case "HandShake02":
                            masters[Index].WriteSingleRegister(0, 18, (ushort)Value);
                            break;
                        case "HandShake03":
                            masters[Index].WriteSingleRegister(0, 19, (ushort)Value);
                            break;
                        case "HandShake04":
                            masters[Index].WriteSingleRegister(0, 20, (ushort)Value);
                            break;
                        case "HandShake05":
                            masters[Index].WriteSingleRegister(0, 21, (ushort)Value);
                            break;
                        case "HandShake06":
                            masters[Index].WriteSingleRegister(0, 22, (ushort)Value);
                            break;
                        case "HandShake07":
                            masters[Index].WriteSingleRegister(0, 23, (ushort)Value);
                            break;
                        case "StartSingle":
                            masters[Index].WriteHoldingRegisterFromBool(0, 24, Value == 1);
                            break;
                        case "Continuous":
                            masters[Index].WriteHoldingRegisterFromBool(0, 25, Value == 1);
                            break;
                        case "CommandOnce":
                            masters[Index].WriteHoldingRegisterFromBool(0, 26, Value == 1);
                            break;
                        case "BasSet":
                            masters[Index].WriteHoldingRegisterFromBool(0, 27, Value == 1);
                            break;
                        case "WrkSet":
                            masters[Index].WriteHoldingRegisterFromBool(0, 28, Value == 1);
                            break;
                        default:
                            break;
                    }
                }
                ret = true;
                return ret;
            }
            catch (Exception)
            {
                ret = false;
                return ret;
            }
        }

        public bool WriteObject(int Index, ObjectItems objectItems)
        {
            bool ret = false;
            if (masters[Index] == null)
                return ret;
            ushort address = 80;
            try
            {
                for (int i = 0; i < objectItems.ItemsCount; i++)
                {
                    if (objectItems.Items[i].Array != 1)
                    {
                        DataType type = (DataType)Enum.Parse(typeof(DataType), objectItems.Items[i].Type);
                        string[] bufferdata = objectItems.Items[i].Default.TrimStart('[').TrimEnd(']').Split(',');
                        object data = null;
                        ushort addressBuffer = address;
                        for (int a = 0; a < objectItems.Items[i].Array; a++)
                        {
                            switch (type)
                            {
                                case DataType.USHORT:
                                    data = Convert.ToUInt16(bufferdata[a]);
                                    masters[Index].WriteHoldingRegisterFromUshort(0, addressBuffer, (ushort)data);
                                    addressBuffer += 1;
                                    break;
                                case DataType.INT:
                                    data = Convert.ToInt32(bufferdata[a]);
                                    masters[Index].WriteHoldingRegisterFromInt(0, addressBuffer, (int)data);
                                    addressBuffer += 2;
                                    break;
                                case DataType.FLOAT:
                                    data = Convert.ToSingle(bufferdata[a]);
                                    masters[Index].WriteHoldingRegisterFromFloat(0, addressBuffer, (float)data);
                                    addressBuffer += 2;
                                    break;
                                case DataType.DOUBLE:
                                    data = Convert.ToDouble(bufferdata[a]);
                                    masters[Index].WriteHoldingRegisterFromDouble(0, addressBuffer, (double)data);
                                    addressBuffer += 4;
                                    break;
                                //case DataType.STRING:
                                //    data = bufferdata[a] + "*&";
                                //    masters[Index].WriteHoldingRegisterFromString(0, addressBuffer, (string)data);
                                //    addressBuffer += 8;
                                //    break;
                                case DataType.BOOL:
                                    data = Convert.ToBoolean(bufferdata[a]);
                                    masters[Index].WriteHoldingRegisterFromBool(0, addressBuffer, (bool)data);
                                    addressBuffer += 1;
                                    break;
                                default:
                                    break;
                            }
                        }
                        address += (ushort)(objectItems.Items[i].MaxSize / 2);
                    }
                    else
                    {
                        DataType type = (DataType)Enum.Parse(typeof(DataType), objectItems.Items[i].Type);
                        object data = null;
                        switch (type)
                        {
                            case DataType.USHORT:
                                data = Convert.ToUInt16(objectItems.Items[i].Default);
                                masters[Index].WriteHoldingRegisterFromUshort(0, address, (ushort)data);
                                address += (ushort)(objectItems.Items[i].MaxSize / 2);
                                break;
                            case DataType.INT:
                                data = Convert.ToInt32(objectItems.Items[i].Default);
                                masters[Index].WriteHoldingRegisterFromInt(0, address, (int)data);
                                address += (ushort)(objectItems.Items[i].MaxSize / 2);
                                break;
                            case DataType.FLOAT:
                                data = Convert.ToSingle(objectItems.Items[i].Default);
                                masters[Index].WriteHoldingRegisterFromFloat(0, address, (float)data);
                                address += (ushort)(objectItems.Items[i].MaxSize / 2);
                                break;
                            case DataType.DOUBLE:
                                data = Convert.ToDouble(objectItems.Items[i].Default);
                                masters[Index].WriteHoldingRegisterFromDouble(0, address, (double)data);
                                address += (ushort)(objectItems.Items[i].MaxSize / 2);
                                break;
                            case DataType.STRING:
                                data = objectItems.Items[i].Default + "*&";
                                masters[Index].WriteHoldingRegisterFromString(0, address, (string)data);
                                address += (ushort)(objectItems.Items[i].MaxSize / 2);
                                break;
                            case DataType.BOOL:
                                data = Convert.ToBoolean(objectItems.Items[i].Default);
                                masters[Index].WriteHoldingRegisterFromBool(0, address, (bool)data);
                                address += (ushort)(objectItems.Items[i].MaxSize / 2);
                                break;
                            default:
                                break;
                        }
                    }
                }
                return true;
            }
            catch (Exception)
            {
                return ret;
            }
        }

        public List<string> ReadObject(int Index, ObjectItems objectItems)
        {
            List<string> list = new List<string>();
            if (masters[Index] == null)
                return list;
            ushort address = 80;
            try
            {
                for (int i = 0; i < objectItems.ItemsCount; i++)
                {
                    if (objectItems.Items[i].Array != 1)
                    {
                        ushort addressOne = address;
                        List<string> listbuffer = new List<string>();
                        DataType type = (DataType)Enum.Parse(typeof(DataType), objectItems.Items[i].Type);
                        string data = "";
                        for (int a = 0; a < objectItems.Items[i].Array; a++)
                        {
                            switch (type)
                            {
                                case DataType.USHORT:
                                    data = masters[Index].ReadHoldingRegistersToUshort(0, addressOne).ToString();
                                    listbuffer.Add(data);
                                    addressOne += 1;
                                    break;
                                case DataType.INT:
                                    data = masters[Index].ReadHoldingRegistersToInt(0, addressOne).ToString();
                                    listbuffer.Add(data);
                                    addressOne += 2;
                                    break;
                                case DataType.FLOAT:
                                    data = (masters[Index].ReadHoldingRegistersToFloat(0, addressOne).ToString());
                                    listbuffer.Add(data);
                                    addressOne += 2;
                                    break;
                                case DataType.DOUBLE:
                                    data = masters[Index].ReadHoldingRegistersToDouble(0, addressOne).ToString();
                                    listbuffer.Add(data);
                                    addressOne += 4;
                                    break;
                                //case DataType.STRING:
                                //    data = masters[Index].ReadInputRegistersToString(0, address,8).ToString();
                                //    list.Add(data);
                                //    if (data.Contains("*&"))
                                //        list.Add(data.Substring(0, data.Length - 2));
                                //    else
                                //    {
                                //        list.Add("");
                                //    }
                                //    address += 8;
                                //    break;
                                case DataType.BOOL:
                                    data = masters[Index].ReadHoldingRegistersToBool(0, addressOne).ToString();
                                    listbuffer.Add(data);
                                    addressOne += 1;
                                    break;
                                default:
                                    break;
                            }
                        }
                        list.Add("[" + string.Join(",", listbuffer.ToArray()) + "]");
                        address += (ushort)((objectItems.Items[i].MaxSize) / 2);
                    }
                    else
                    {
                        DataType type = (DataType)Enum.Parse(typeof(DataType), objectItems.Items[i].Type);
                        string data = "";
                        switch (type)
                        {
                            case DataType.USHORT:
                                data = masters[Index].ReadHoldingRegistersToUshort(0, address).ToString();
                                list.Add(data);
                                address += (ushort)((objectItems.Items[i].MaxSize) / 2);
                                break;
                            case DataType.INT:
                                data = masters[Index].ReadHoldingRegistersToInt(0, address).ToString();
                                list.Add(data);
                                address += (ushort)((objectItems.Items[i].MaxSize) / 2);
                                break;
                            case DataType.FLOAT:
                                data = masters[Index].ReadHoldingRegistersToFloat(0, address).ToString();
                                list.Add(data);
                                address += (ushort)((objectItems.Items[i].MaxSize) / 2);
                                break;
                            case DataType.DOUBLE:
                                data = masters[Index].ReadHoldingRegistersToDouble(0, address).ToString();
                                list.Add(data);
                                address += (ushort)((objectItems.Items[i].MaxSize) / 2);
                                break;
                            case DataType.STRING:
                                data = (masters[Index].ReadHoldingRegistersToString(0, address, (ushort)(objectItems.Items[i].MaxSize / 2)).ToString()).Trim();
                                if (data.Contains("*&"))
                                {
                                    string bb = data.Substring(0, data.IndexOf("*&"));
                                    list.Add(bb);
                                }
                                else
                                {
                                    list.Add("");
                                }
                                address += (ushort)((objectItems.Items[i].MaxSize) / 2);
                                break;
                            case DataType.BOOL:
                                data = masters[Index].ReadHoldingRegistersToBool(0, address).ToString();
                                list.Add(data);
                                address += (ushort)((objectItems.Items[i].MaxSize) / 2);
                                break;
                            default:
                                break;
                        }
                    }
                }
                return list;
            }
            catch (Exception ex)
            {
                return list;
            }
        }

        static bool[] IntToBoolArray(int number)
        {
            bool[] result = new bool[32];
            for (int i = 0; i < 32; i++)
            {
                result[i] = (number & (1 << i)) != 0;
            }
            return result;
        }

    }
}
